/**
 *  Copyright(C) 2012-2013 Suntec(Shanghai) Software Co., Ltd.
 *  All Right Reserved.
 */
package com.cugbmao.lucene;

import junit.framework.TestCase;

import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;

import com.cugbmao.lucene.util.TestUtil;

/**
 * Descriptions
 * 
 * @version 2013年5月27日
 * @author Suntec
 * @since JDK1.6
 * 
 */
public class BasicSearchingTest extends TestCase {

	public void testTerm() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		Term t = new Term( "subject", "ant" );
		Query query = new TermQuery( t );
		TopDocs docs = searcher.search( query, 10 );
		System.out.println( docs.totalHits );
		assertEquals( "Ant in Action", 1, docs.totalHits );
		t = new Term( "subject", "junit" );
		docs = searcher.search( new TermQuery( t ), 10 );
		System.out.println( docs.totalHits );
		assertEquals( "Ant in Action, " + "Junit in Action Second Edition", 2, docs.totalHits );
		reader.close();
		dir.close();
	}

	public void testQueryParser() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		QueryParser parser = new QueryParser( Version.LUCENE_43, "contents", new SimpleAnalyzer( Version.LUCENE_43 ) );

		Query query = parser.parse( "+JUNIT +ANT -MOCK" );

		TopDocs docs = searcher.search( query, 10 );

		assertEquals( 1, docs.totalHits );
		Document d = searcher.doc( docs.scoreDocs[0].doc );
		assertEquals( "Ant in Action", d.get( "title" ) );

		query = parser.parse( "mock OR junit" );
		docs = searcher.search( query, 10 );
		assertEquals( "Ant int Action, JUnit in Action, Second Edition", 2, docs.totalHits );
		reader.close();
		dir.close();
	}

	public void testKeyword() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		Term t = new Term( "isbn", "9781935182023" );
		Query query = new TermQuery( t );
		TopDocs docs = searcher.search( query, 10 );
		assertEquals( "Junit in Action, Second Edition", 1, docs.totalHits );

		reader.close();
		dir.close();
	}

	public void testTermRangeQuery() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		TermRangeQuery query = new TermRangeQuery( "title2", new BytesRef( "d" ), new BytesRef( "j" ), true, true );
		TopDocs docs = searcher.search( query, 100 );
		assertEquals( 3, docs.totalHits );
		reader.close();
		dir.close();
	}

	public void testNumericRangeQuery() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		NumericRangeQuery<Integer> query = NumericRangeQuery.newIntRange( "pubmonth", 200605, 200609, true, true );
		TopDocs docs = searcher.search( query, 10 );
		assertEquals( 1, docs.totalHits );
		reader.close();
		dir.close();
	}

	public void testPrefixQuery() throws Exception {
		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		Term t = new Term( "category", "/technology/computers/programming" );
		PrefixQuery query = new PrefixQuery( t );

		TopDocs docs = searcher.search( query, 10 );
		int programmingAndBelow = docs.totalHits;

		docs = searcher.search( new TermQuery( t ), 10 );
		int justProgramming = docs.totalHits;

		assertTrue( programmingAndBelow > justProgramming );
		reader.close();
		dir.close();
	}

	public void testAdd() throws Exception {
		TermQuery query = new TermQuery( new Term( "subject", "search" ) );
		Query books2010 = NumericRangeQuery.newIntRange( "pubmonth", 201001, 201012, true, true );

		BooleanQuery searchingBooks2010 = new BooleanQuery();

		searchingBooks2010.add( query, BooleanClause.Occur.MUST );
		searchingBooks2010.add( books2010, BooleanClause.Occur.MUST );

		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		TopDocs docs = searcher.search( searchingBooks2010, 10 );

		assertTrue( TestUtil.hitsIncludeTitle( searcher, docs, "Lucene in Action, Second Edition" ) );
		reader.close();
		dir.close();
	}

	public void testOr() throws Exception {
		TermQuery methodologyBooks = new TermQuery( new Term( "category",
				"/technology/computers/programming/methodology" ) );
		TermQuery easternPhilosophyBooks = new TermQuery( new Term( "category", "/philosophy/eastern" ) );

		BooleanQuery query = new BooleanQuery();
		query.add( methodologyBooks, BooleanClause.Occur.SHOULD );
		query.add( easternPhilosophyBooks, BooleanClause.Occur.SHOULD );

		Directory dir = TestUtil.getBookIndexDirectory();
		IndexReader reader = DirectoryReader.open( dir );
		IndexSearcher searcher = new IndexSearcher( reader );

		TopDocs docs = searcher.search( query, 10 );
		System.out.println( "or = " + query );

		assertTrue( TestUtil.hitsIncludeTitle( searcher, docs, "Extreme Programming Explained" ) );
		assertTrue( TestUtil.hitsIncludeTitle( searcher, docs, "Tao Te Ching \u9053\u5FB7\u7D93" ) );

		reader.close();
		dir.close();
	}
}
